﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using ServerClientCommon;

namespace SensorClient
{
    public class TcpClientModel
    {

        #region Constants
        /// <summary>
        /// The maximum size of an message
        /// </summary>
        private const int MAX_MESSAGE_SIZE = 1024;
        #endregion

        #region Members
        /// <summary>
        /// The object used to manage an tcp client
        /// </summary>
        private TcpClient _client;
        /// <summary>
        /// An object containing the IP address and port used
        /// for a tcp/ip connection.
        /// </summary>
        private IPEndPoint _ip;
        /// <summary>
        /// If true, the client is connected to the server. Otherwise
        /// the client is not connected to the server.
        /// </summary>
        private bool _isConnected;
        /// <summary>
        /// The stream used to connect the server and the client
        /// </summary>
        private NetworkStream _stream;
        #endregion

        #region Constructors
        /// <summary>
        /// Creates a TcpClientModel object
        /// </summary>
        /// <param name="ipAdress">The server's IP</param>
        /// <param name="port">The server's port</param>
        public TcpClientModel(string ipAdress, int port)
        {
            try
            {
                _isConnected = false;
                _client = new TcpClient();
                _ip = new IPEndPoint(IPAddress.Parse(ipAdress), port);
                _client.Connect(_ip);
            }
            catch (Exception ex)
            {
                Console.Write("Could not connect to server: " + ex.Message +"\n");
            }
        }
        #endregion

        #region Public methods
        /// <summary>
        /// Sends a message to the server
        /// </summary>
        /// <param name="message">The message</param>
        public void SendMessage(string message)
        {
            try
            {
                message = CipherUtility.Encrypt<AesManaged>(message, 
                                                            CipherUtility.DEFAULT_PASSWORD, 
                                                            CipherUtility.DEFAULT_SALT);
                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] buffer = encoder.GetBytes(message);
                _stream.Write(buffer, 0, buffer.Length);
                _stream.Flush();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not send message to server: " + ex.Message +"\n");
            }
        }

        /*
        /// <summary>
        /// Receives a message from the server
        /// </summary>
        /// <returns>The message</returns>
        public string ReceiveMessage()
        {
            try
            {
                byte[] buffer = new byte[MAX_MESSAGE_SIZE];
                _stream.Read(buffer, 0, MAX_MESSAGE_SIZE);
                _stream.Flush();
                ASCIIEncoding encoder = new ASCIIEncoding();
                string message = encoder.GetString(buffer);
                return message;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not receive message from server: " + ex.Message);
                return null;
            }
        }
        */

        /// <summary>
        /// Connects the client to the server
        /// </summary>
        public void Connect()
        {
            try
            {
                _stream = _client.GetStream();
                _isConnected = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not connect to server: " + ex.Message);
            }
        }

        /// <summary>
        /// Stops the client from sending/receiveing messages from
        /// the server.
        /// </summary>
        public void Disconnect()
        {
            try
            {
                _stream.Close();
                _isConnected = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not disconnect from server: " + ex.Message +"\n");
            }
        }

        #endregion

        #region Properites
        /// <summary>
        /// Returns true if the client is connected to the server
        /// </summary>
        public bool IsConnected
        {
            get { return _isConnected; }
        }
        #endregion

    }
}
